﻿using System;
using System.Reflection;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace HyperPin_Database_Editor {
    public partial class MainForm : Form
    {
        public static MainForm theMainForm;
        public string currentSettingsFileName;
        public string hyperPinDirectory;

        // ==== Visual Pinball Objects ====
        VisualPinballDatabase vpDatabase;
        FuturePinballDatabase fpDatabase;

        // Favorites (uses HashSet to ensure tables only occur once)
        HashSet<string> favoriteTables;

        public MainForm()
        {
            theMainForm = this;

            InitializeComponent();

            // add hander for the tab control changing selections
            // mostly so we can tweak the menus to match.
            tabControl.Selected += new System.Windows.Forms.TabControlEventHandler(this.TabControl_Selected);

            // Set the default -- "about" detail view in the hyperpin settings panel.
            splitContainerHP.Panel2.Controls.Add(new HPAboutSettings());
        }

        // ==== Menu and Action Response Handlers ====
        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            openFileDialog.FileName = "HyperPin.exe";
            openFileDialog.Filter = "Executable Files (*.exe)|*.exe|All Files (*.*)|*.*";
            openFileDialog.FilterIndex = 1;
            DialogResult result = openFileDialog.ShowDialog();
            if (result == DialogResult.OK)
            {
                //toolStripStatusLabelHyperPinExe.Text = openFileDialog.FileName;
                hyperPinDirectory = Path.GetDirectoryName(openFileDialog.FileName);

                OpenHyperPinSettings();
                OpenVisualPinballDatabase();
                OpenFuturePinballDatabase();
                OpenFavoritesList();
            }
        }

        private void closeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Not yet implemented");

            // CloseHyperPinSettings();
            // CloseVisualPinballDatabase();
            // CloseFuturePinballDatabase();
            // CloseFavoritesList();
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            tabControl.SelectedTab.Focus();

            // Save the various files...
            SaveHyperPinSettings();
            SaveVisualPinballDatabase();
            SaveFuturePinballDatabase();
            SaveFavoritesList();
        }

        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Not yet implemented");
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void TabControl_Selected(Object sender, TabControlEventArgs e)
        {
            // Disable all context sensitive menu items
            tablesToolStripMenuItem.Enabled = false;
            removeTableToolStripMenuItem.Enabled = false;

            // Enable context sensitive menu items when on the right tabs (contexts)
            if ((tabControl.SelectedTab == tabVP && vpDatabase != null) ||
                (tabControl.SelectedTab == tabFP && fpDatabase != null))
            {
                tablesToolStripMenuItem.Enabled = true;
                removeTableToolStripMenuItem.Enabled = true;
            }
        }

        // ==== Tables menu items ====
        private void newTableToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // New table is only valid for Visual Pinball (VP) and Future Pinball (FP) tabs

            if (tabControl.SelectedTab == tabVP)
            {
                TableSummary newTable = vpDatabase.AddNew();
                listVPTables.SetSelected(listVPTables.Items.IndexOf(newTable), true);
            }

            if (tabControl.SelectedTab == tabFP)
            {
                TableSummary newTable = fpDatabase.AddNew();
                listFPTables.SetSelected(listFPTables.Items.IndexOf(newTable), true);
            }
        }

        private void newTableFromXMLToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TableDatabase db = null;
            ListBox listBox = null;
            if (tabControl.SelectedTab == tabVP)
            {
                db = vpDatabase;
                listBox = listVPTables;
            }

            if (tabControl.SelectedTab == tabFP)
            {
                db = fpDatabase;
                listBox = listFPTables;
            }

            if (db != null && listBox != null)
            {
                // New table is only valid for Visual Pinball (VP) and Future Pinball (FP) tabs
                NewTableDialog newTableDialog = new NewTableDialog();
                DialogResult result = newTableDialog.ShowDialog();
                if (result == DialogResult.OK)
                {
                    TableSummary newTable = db.AddNew();
                    newTable.TableName = newTableDialog.TableName;
                    newTable.TableDescription = newTableDialog.TableDescription;
                    newTable.TableManufacturer = newTableDialog.TableManufacturer;
                    newTable.TableYear = newTableDialog.TableYear;
                    newTable.TableType = newTableDialog.TableType;
                        
                    listBox.SetSelected(listBox.Items.IndexOf(newTable), true);                    
                }
            }
        }

        private void removeTableToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Remove table is only valid for Visual Pinball (VP) and Future Pinball (FP) tabs
            TableDatabase db = null;
            ListBox listBox = null;
            if (tabControl.SelectedTab == tabVP)
            {
                db = vpDatabase;
                listBox = listVPTables;
            }

            if (tabControl.SelectedTab == tabFP)
            {
                db = fpDatabase;
                listBox = listFPTables;
            }

            if (db != null && listBox != null)
            {
                // Must have a table selected from the list
                if (listBox.SelectedItem != null)
                {
                    string tableName = ((TableSummary)listBox.SelectedItem).TableName;
                    string message = String.Format("Remove table named \"{0}\" from HyperPin's database?", tableName);
                    DialogResult result = MessageBox.Show(message, "Confirm Remove", MessageBoxButtons.YesNo);
                    if (result == DialogResult.Yes)
                    {
                        db.Remove((TableSummary)listBox.SelectedItem);
                    }
                }
            }
        }

        private void checkTablesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CheckTablesDialog checkDialog = new CheckTablesDialog();
            checkDialog.tableDatabase = vpDatabase;
            checkDialog.ShowDialog();
        }

        // ==== Visual Pinball Tab Routines ====
        private void OpenVisualPinballDatabase()
        {
            vpDatabase = new VisualPinballDatabase();
            vpDatabase.LoadDatabase(hyperPinDirectory);

            listVPTables.DataSource = vpDatabase;
            listVPTables.DisplayMember = "TableDescription";
            
            //textVPTableName.DataBindings.Add("Text", vpDatabase, "TableName", false, DataSourceUpdateMode.OnPropertyChanged);
            textVPTableName.DataBindings.Add("Text", vpDatabase, "TableName");
            textVPDescription.DataBindings.Add("Text", vpDatabase, "TableDescription");
            comboVPManufacturer.DataBindings.Add("Text", vpDatabase, "TableManufacturer");
            comboVPYear.DataBindings.Add("Text", vpDatabase, "TableYear");
            comboVPType.DataBindings.Add("Text", vpDatabase, "TableType");
            textVPXml.DataBindings.Add("Text", vpDatabase, "TableXml");
            checkVPFavorite.DataBindings.Add("Checked", vpDatabase, "Favorite");
            
            //listVPTables.Items.AddRange(vpDatabase.getTableNames());
            comboVPManufacturer.Items.AddRange(vpDatabase.GetManufacturerNames());
            comboVPType.Items.AddRange(vpDatabase.GetTableTypes());
            comboVPYear.Items.AddRange(vpDatabase.GetTableYears());
        }

        private void listVPTables_SelectedIndexChanged(object sender, EventArgs e)
        {
            // Enable the "remove table" menu item
            removeTableToolStripMenuItem.Enabled = true;
        }

        private void SaveVisualPinballDatabase()
        {
            vpDatabase.SaveDatabase();
        }

        // ==== Future Pinball Routines ====
        private void OpenFuturePinballDatabase()
        {
            fpDatabase = new FuturePinballDatabase();
            fpDatabase.LoadDatabase(hyperPinDirectory);

            listFPTables.DataSource = fpDatabase;
            listFPTables.DisplayMember = "TableDescription";

            textFPTableName.DataBindings.Add("Text", fpDatabase, "TableName");
            textFPDescription.DataBindings.Add("Text", fpDatabase, "TableDescription");
            comboFPManufacturer.DataBindings.Add("Text", fpDatabase, "TableManufacturer");
            comboFPYear.DataBindings.Add("Text", fpDatabase, "TableYear");
            comboFPType.DataBindings.Add("Text", fpDatabase, "TableType");
            textFPXml.DataBindings.Add("Text", fpDatabase, "TableXml");
            checkFPFavorite.DataBindings.Add("Checked", fpDatabase, "Favorite");

            comboFPManufacturer.Items.AddRange(vpDatabase.GetManufacturerNames());
            comboFPType.Items.AddRange(vpDatabase.GetTableTypes());
            comboFPYear.Items.AddRange(vpDatabase.GetTableYears());
        }

        private void SaveFuturePinballDatabase()
        {
            fpDatabase.SaveDatabase();
        }

        // ==== HyperPin Tab Routines ====
        private void OpenHyperPinSettings()
        {
            treeHyperPin.Nodes.Clear();

            currentSettingsFileName = Path.Combine(hyperPinDirectory, "Settings", "Settings.ini");

            Assembly currentAssembly = Assembly.GetExecutingAssembly();
            IniFile settingsINI = new IniFile(currentSettingsFileName);
            string[] sections = settingsINI.IniReadSectionNames();
            if (sections == null)
            {
                MessageBox.Show("There was an error opening the Settings.ini file for HyperPin. Is there a Settings directory in the HyperPin.exe location?");
                return;
            }

            foreach (string section in sections)
            {
                TreeNode node = treeHyperPin.Nodes.Add(section);
                node.Name = section;
                node.Tag = section;

                HPSettingsPanel settingControl = (HPSettingsPanel)currentAssembly.CreateInstance(hyperPinControlNameForTitle(section));
                if (settingControl == null)
                {
                    settingControl = new HPGenericSettings();
                }

                settingControl.Hide();
                settingControl.Tag = section;
                settingControl.Dock = DockStyle.Fill;
                settingControl.setSettingsFileName(currentSettingsFileName);
                settingControl.setSettingsSection(section);
                settingControl.doLoadSettings();
                splitContainerHP.Panel2.Controls.Add(settingControl);
            }
        }

        private void SaveHyperPinSettings()
        {
            foreach (Control theControl in splitContainerHP.Panel2.Controls)
            {
                HPSettingsPanel theSettingsPanel = (HPSettingsPanel)theControl;
                theSettingsPanel.doSaveSettings();
            }
        }

        private void treeHyperPin_BeforeSlect(object sender, TreeViewCancelEventArgs e)
        {
            foreach (Control theControl in splitContainerHP.Panel2.Controls)
            {
                theControl.Hide();
            }
        }

        private void treeHyperPin_AfterSelect(object sender, TreeViewEventArgs e)
        {
            string nodeNameToLoad = (string)treeHyperPin.SelectedNode.Tag;
            string theControlName;
            foreach (Control theControl in splitContainerHP.Panel2.Controls)
            {
                theControlName = (string)theControl.Tag;
                if (nodeNameToLoad == theControlName)
                {
                    theControl.Show();
                }
                else
                {
                    theControl.Hide();
                }
            }
        }

        private string hyperPinControlNameForTitle(string title)
        {
            string myNamespace = this.GetType().Namespace;
            return myNamespace + ".HP" + title.Replace(" ", "") + "Settings";
        }

        // ===== Favorites List Routines =====
        public void OpenFavoritesList()
        {
            // remove old favorite tables, if exists...
            if (favoriteTables != null)
            {
                favoriteTables.Clear();
                favoriteTables = null;
            }

            string favoriteFileName = Path.Combine(hyperPinDirectory, "favorites.txt");
            try 
            {
                TextReader favoriteReader = new StreamReader(favoriteFileName);
                favoriteTables = new HashSet<string>();

                string tableName = favoriteReader.ReadLine();
                while (tableName != null)
                {
                    setFavroiteTable(tableName, true);
                    tableName = favoriteReader.ReadLine();
                }

                favoriteReader.Close();
            }
            catch (System.IO.IOException e)
            {
                // No favorites file.
            }
        }

        public void SaveFavoritesList()
        {
            if (favoriteTables != null)
            {
                string favoriteFileName = Path.Combine(hyperPinDirectory, "favorites.txt");
                try
                {
                    TextWriter favoriteWriter = new StreamWriter(favoriteFileName);
                    foreach (string tableName in favoriteTables)
                    {
                        favoriteWriter.WriteLine(tableName);
                    }

                    favoriteWriter.Close();
                }
                catch (System.IO.IOException e)
                {
                    string errorMessage = string.Format("Could not save favorites file {0}.", favoriteFileName);
                    MessageBox.Show(errorMessage);
                }
            }
        }

        public bool isFavoriteTable(string tableName)
        {
            if (favoriteTables != null)
            {
                return favoriteTables.Contains(tableName);
            }

            return false;
        }

        public void setFavroiteTable(string tableName, bool makeFavorite)
        {
            if (favoriteTables == null)
            {
                favoriteTables = new HashSet<string>();
            }

            if (makeFavorite)
            {
                favoriteTables.Add(tableName);
            }
            else
            {
                favoriteTables.Remove(tableName);
            }
        }
    }
}
